package log

import (
	"log"
	"time"

	"gitee.com/zawei/yggdrasil/pkg/config"
	"gitee.com/zawei/yggdrasil/pkg/log/zap"
	zap1 "go.uber.org/zap"
)

var (
	logger       Logger
	initClosedCh = make(chan struct{})
)

func init() {
	cfg := &zap.Config{}
	if err := config.Get("log.zap").Scan(&cfg); err != nil {
		log.Fatal(err)
	}
	cfg.CallerSkip = 1
	lg := cfg.Build()
	logger = lg
	w, err := config.Watch("log.zap.level")
	if err != nil {
		Fatalw("fault to watch config", "key", "log.zap.level", "error", err)
	}
	go func() {
		for {
			val, err := w.Next()
			if err != nil {
				if err.Error() == "watcher stopped" {
					return
				}
				Errorw("fault to get next config", "key", "log.zap.level", "error", err)
				time.Sleep(time.Second * 2)
				continue
			}
			lv := zap1.InfoLevel
			if err := lv.UnmarshalText(val.Bytes()); err != nil {
				Errorw("fault to unmarshal log level", "error", err)
				continue
			}
			lg.SetLevel(lv)
		}
	}()
	go func() {
		select {
		case <-initClosedCh:
			_ = w.Stop()
		}
	}()
}

func SetLogger(lg Logger) {
	close(initClosedCh)
	logger = lg
}

// Debug is debug level
func Debug(args ...interface{}) {
	logger.Debug(args...)
}

// Info is info level
func Info(args ...interface{}) {
	logger.Info(args...)
}

// Warn is warning level
func Warn(args ...interface{}) {
	logger.Warn(args...)
}

// Error is error level
func Error(args ...interface{}) {
	logger.Error(args...)
}

// Error is fault level
func Fatal(args ...interface{}) {
	logger.Fatal(args...)
}

// Debugf is format debug level
func Debugf(fmt string, args ...interface{}) {
	logger.Debugf(fmt, args...)
}

// Infof is format info level
func Infof(fmt string, args ...interface{}) {
	logger.Infof(fmt, args...)
}

// Warnf is format warning level
func Warnf(fmt string, args ...interface{}) {
	logger.Warnf(fmt, args...)
}

// Errorf is format error level
func Errorf(fmt string, args ...interface{}) {
	logger.Errorf(fmt, args...)
}

// Fatalf is format fatal level
func Fatalf(fmt string, args ...interface{}) {
	logger.Fatalf(fmt, args...)
}

// Debugw is format debug level
func Debugw(fmt string, args ...interface{}) {
	logger.Debugw(fmt, args...)
}

// Infow is format info level
func Infow(fmt string, args ...interface{}) {
	logger.Infow(fmt, args...)
}

// Warnw is format warning level
func Warnw(fmt string, args ...interface{}) {
	logger.Warnw(fmt, args...)
}

// Errorw is format error level
func Errorw(fmt string, args ...interface{}) {
	logger.Errorw(fmt, args...)
}

// Fatalw is format fatal level
func Fatalw(fmt string, args ...interface{}) {
	logger.Fatalw(fmt, args...)
}
